home *** CD-ROM | disk | FTP | other *** search
/ Adobe Graphics & Publishing SDK 1996 December / Adobe Graphics & Publishing SDK 1996 December.iso / pc / ps40sdk / examples / selection / selectorama / common / selectorama.c next >
Encoding:
C/C++ Source or Header  |  1996-10-09  |  12.5 KB  |  536 lines

  1. /*
  2.    File: Selectorama.c
  3.  
  4.    Copyright 1996, Adobe Systems Incorporated.  All rights reserved.
  5.    
  6. */
  7.  
  8. #if __MWERKS__
  9. #include <SetupA4.h> // A4-globals
  10. #include <A4Stuff.h> // A4-globals
  11. #endif
  12.  
  13. #if defined(THINK_C) || defined(__MWERKS__)
  14. #define ENTRYPOINT main
  15. #endif
  16.  
  17. #include "Selectorama.h"
  18.  
  19. Handle hDllInstance = NULL;
  20.  
  21. /*****************************************************************************/
  22.  
  23. void InitGlobals (GPtr globals);
  24. void TrimVRect (VRect *dst, VRect *src);
  25. static Boolean EqualVRects (VRect *a, VRect *b);
  26. static int32 AccountChannel (ReadChannelDesc *source,
  27.                                       ReadChannelDesc *mask,
  28.                                       WriteChannelDesc *dest);
  29. static void ApplyChannel (GPtr globals, ReadChannelDesc *source, PixelMemoryDesc *sDesc,
  30.                                   ReadChannelDesc *mask, PixelMemoryDesc *mDesc,
  31.                                   WriteChannelDesc *dest, ChannelReadPort destRead,
  32.                                   PixelMemoryDesc *dDesc, PixelMemoryDesc *rDesc,
  33.                                   int32 *done, int32 total);
  34. void DoExecute (GPtr globals);
  35.  
  36. /*****************************************************************************/
  37.  
  38. /* All calls to the plug-in module come through this routine. It must be
  39.    placed first in the resource. To achieve this, most development systems
  40.    require that this be the first routine in the source. */
  41.  
  42. #if MSWindows
  43. void ENTRYPOINT (short selector,
  44.                         PISelectionParams *selectionParamBlock,
  45.                         long *data,
  46.                         short *result)                
  47. #else
  48. pascal void ENTRYPOINT (short selector,
  49.                         PISelectionParams *selectionParamBlock,
  50.                         long *data,
  51.                         short *result)                
  52. #endif
  53.     {
  54.     
  55.     Globals globalValues;
  56.     GPtr globals = &globalValues;
  57.     
  58.     #if __MWERKS__
  59.     EnterCodeResource(); // A4-globals
  60.     #endif
  61.     
  62.     if (!*data)
  63.         {
  64.         
  65.         InitGlobals (globals);
  66.  
  67.         *data = (long) NewHandle (sizeof (Globals));
  68.         
  69.         if (!*data)
  70.             {
  71.             *result = memFullErr;
  72.             return;
  73.             }
  74.             
  75.         ** (GHdl) *data = globalValues;
  76.         
  77.         }
  78.         
  79.     globalValues = ** (GHdl) *data;
  80.         
  81.     gStuff = selectionParamBlock;
  82.     gResult = noErr;
  83.    
  84.     switch (selector)
  85.     {
  86.         
  87.         case selectionSelectorAbout:
  88.             DoAbout (globals);
  89.             break;
  90.             
  91.         case selectionSelectorExecute:
  92.             DoExecute (globals);
  93.             break;
  94.             
  95.         default:
  96.             gResult = selectionBadParameters;
  97.     }
  98.         
  99.     *result = gResult;
  100.     ** (GHdl) *data = globalValues;
  101.  
  102.     #if __MWERKS__
  103.     ExitCodeResource(); // A4-globals
  104.     #endif
  105. }
  106.  
  107. /*****************************************************************************/
  108.  
  109. void InitGlobals (GPtr globals)
  110. {
  111.     
  112.     gWhatArea = iSelectMin;
  113.     gWhatChannels = iUseTarget;
  114.     gPercent = 50;
  115.     gCreate = iCreateSelection;
  116.     gQueryForParameters = false;
  117.     
  118. }    
  119.  
  120. /*****************************************************************************/
  121.  
  122. static void TrimVRect (VRect *dst, VRect *src)
  123.     {
  124.     
  125.     if (dst->top    < src->top   ) dst->top    = src->top;
  126.     if (dst->left   < src->left  ) dst->left   = src->left;
  127.     if (dst->bottom > src->bottom) dst->bottom = src->bottom;
  128.     if (dst->right  > src->right ) dst->right  = src->right;
  129.     
  130.     }
  131.  
  132. /*****************************************************************************/
  133.  
  134. static Boolean EqualVRects (VRect *a, VRect *b)
  135.     {
  136.     
  137.     return  a->top    == b->top
  138.          && a->left   == b->left
  139.          && a->bottom == b->bottom
  140.          && a->right  == b->right;
  141.     
  142.     }
  143.  
  144. /*****************************************************************************/
  145.  
  146. static int32 AccountChannel (ReadChannelDesc *source,
  147.                                       ReadChannelDesc *mask,
  148.                                       WriteChannelDesc *dest)
  149.     {
  150.     
  151.     VRect limit;
  152.     
  153.     limit = source->bounds;
  154.     TrimVRect (&limit, &dest->bounds);
  155.     if (mask != NULL) TrimVRect (&limit, &mask->bounds);
  156.         
  157.     if (limit.right <= limit.left || limit.bottom <= limit.top) return 0;
  158.     
  159.     return (limit.right - limit.left) * (limit.bottom - limit.top);
  160.     
  161.     }
  162.  
  163. /*****************************************************************************/
  164.  
  165. static void ApplyChannel (GPtr globals,
  166.                           ReadChannelDesc *source,
  167.                           PixelMemoryDesc *sDesc,
  168.                           ReadChannelDesc *mask, 
  169.                           PixelMemoryDesc *mDesc,
  170.                           WriteChannelDesc *dest, 
  171.                           ChannelReadPort destRead,
  172.                           PixelMemoryDesc *dDesc,
  173.                           PixelMemoryDesc *rDesc,
  174.                           int32 *done,
  175.                           int32 total)
  176.     {
  177.     
  178.     VRect limit;
  179.     int32 row, col, row2, col2;
  180.     unsigned8 *s, *m, *d;
  181.     unsigned8 *r = (unsigned8 *)rDesc->data;
  182.     Boolean initRandom = (*r == kInitRandom);
  183.         
  184.     limit = source->bounds;
  185.     TrimVRect (&limit, &dest->bounds);
  186.     if (mask != NULL) TrimVRect (&limit, &mask->bounds);
  187.         
  188.     if (limit.right <= limit.left || limit.bottom <= limit.top) return;
  189.     
  190.     for (row = limit.top; row < limit.bottom; row += kBlockRows)
  191.         for (col = limit.left; col < limit.right; col += kBlockCols)
  192.             {
  193.             
  194.             VRect area;
  195.             PSScaling scaling;
  196.             VRect wrote;
  197.             
  198.             if (TestAbort ())
  199.                 {
  200.                 gResult = userCanceledErr;
  201.                 return;
  202.                 }
  203.             
  204.             area.top = row;  area.bottom = row + kBlockRows;
  205.             area.left = col; area.right  = col + kBlockCols;
  206.             
  207.             if (limit.bottom < area.bottom) area.bottom = limit.bottom;
  208.             if (limit.right  < area.right ) area.right  = limit.right;
  209.             
  210.             scaling.sourceRect = area;
  211.             scaling.destinationRect = area;
  212.             
  213.             gResult = ReadPixels (destRead, &scaling, &area, dDesc, &wrote);
  214.             if (gResult != noErr) return;
  215.             
  216.             if (!EqualVRects (&area, &wrote))
  217.                 {
  218.                 gResult = -1;
  219.                 return;
  220.                 }
  221.                 
  222.             gResult = ReadPixels (source->port, &scaling, &area, sDesc, &wrote);
  223.             if (gResult != noErr) return;
  224.             
  225.             if (!EqualVRects (&area, &wrote))
  226.                 {
  227.                 gResult = -1;
  228.                 return;
  229.                 }
  230.                 
  231.             if (mask != NULL)
  232.                 {
  233.                 
  234.                 gResult = ReadPixels (mask->port, &scaling, &area, mDesc, &wrote);
  235.                 if (gResult != noErr) return;
  236.                 
  237.                 if (!EqualVRects (&area, &wrote))
  238.                     {
  239.                     gResult = -1;
  240.                     return;
  241.                     }
  242.                 }
  243.                 m = (unsigned8 *) mDesc->data;
  244.                 /* mask all set and ready to go */
  245.                                     
  246.             /* heart of the routine.  Compares source pixel and destination
  247.                pixel and, if destination is smaller, replaces it with
  248.                source */
  249.  
  250.             s = (unsigned8 *) sDesc->data;
  251.             d = (unsigned8 *) dDesc->data;
  252.             r = (unsigned8 *) rDesc->data;
  253.                         
  254.             for (row2 = kBlockRows; row2 > 0; --row2)
  255.                 for (col2 = kBlockCols; col2 > 0; --col2)
  256.                 {
  257.                     
  258.                     switch (gWhatArea)
  259.                     {
  260.                         case iSelectMin:
  261.                             if (mask != NULL && *m < *s ) *s = *m;
  262.                             if (*s > 127) *d = *s;
  263.                             else *d = 0;
  264.                             break;
  265.                         case iSelectMax:
  266.                             if (mask != NULL && *m < *s ) *s = *m;
  267.                             if (*s < 128) *d = 255 - *s; // if (*d < *s) *d = *s;
  268.                             else *d = 0;
  269.                             break;
  270.                         case iSelectRandom:
  271.                             if (initRandom)
  272.                             {
  273.                                 if ((((unsigned16) Random ()) % 100) < gPercent)
  274.                                     *r = kRandomOn; // flag as picked
  275.                                 else *r = kRandomOff; // flag as off
  276.                             }
  277.                             if (*r == kRandomOn)
  278.                                 *d = 255;
  279.                             else *d = 0;
  280.                             break;
  281.                     }
  282.                     ++s;
  283.                     ++d;
  284.                     ++r;
  285.                     if (mask != NULL) ++m;
  286.                 }
  287.                     
  288.             gResult = WritePixels (dest->port, &area, dDesc);
  289.             if (gResult != noErr) return;
  290.             
  291.             *done += (area.right - area.left) * (area.bottom - area.top);
  292.             
  293.             UpdateProgress (*done, total);
  294.                 
  295.             }
  296.     
  297.     }
  298.  
  299. /*****************************************************************************/
  300.  
  301. void DoExecute (GPtr globals)
  302. {
  303.     
  304.     int32 total = 0;
  305.     int32 done = 0;
  306.     Ptr        p = 0;
  307.     
  308.     Boolean    doThis = true;
  309.     
  310.     BufferID sBuffer = 0;
  311.     Ptr sData = NULL;
  312.     BufferID dBuffer = 0;
  313.     Ptr dData = NULL;
  314.     BufferID mBuffer = 0;
  315.     Ptr mData = NULL;
  316.     BufferID rBuffer = 0;
  317.     Ptr rData = NULL;
  318.     
  319.     PixelMemoryDesc sDesc, dDesc, mDesc, rDesc;
  320.  
  321.     ReadImageDocumentDesc *doc = gStuff->documentInfo;
  322.     WriteChannelDesc *selection = gStuff->newSelection;
  323.     ChannelReadPort selectionRead;
  324.     ReadChannelDesc *composite;
  325.     ReadChannelDesc *transparency;
  326.     ReadChannelDesc *curChannel;
  327.     
  328.     
  329.     /* Access the port procs. */
  330.     
  331.     if (!WarnChannelPortAvailable ())
  332.         {
  333.         gResult = errPlugInHostInsufficient;
  334.         goto CleanUp;
  335.         }
  336.         
  337.     gQueryForParameters = ReadScriptParams (globals);
  338.     
  339.     if ( gQueryForParameters ) doThis = DoParameters (globals);
  340.     
  341.     if ( !doThis ) goto CleanUp; // user cancelled, etc.
  342.     
  343.     /* look in gStuff->supportedTreatments for support for this next thang */
  344.         
  345.     if (gCreate == iCreateMaskpath)
  346.     { // can't do that!
  347.         p = PIGetResource (StringResource, errCantCreatePath, &total);
  348.         if (p) 
  349.         {
  350.             gResult = PIReportError((unsigned char *)p);
  351.             PIReleaseResource(p);
  352.         }
  353.         else gStuff->treatment = KeyToEnum(EnumToKey(gCreate,typeCreate),typePISel);
  354.         // otherwise Pshop will catch it automatically
  355.         goto CleanUp;
  356.     }
  357.     else
  358.         gStuff->treatment = KeyToEnum(EnumToKey(gCreate,typeCreate),typePISel);
  359.         // got it.  Move on.
  360.  
  361.     /* We will need a read port for the selection. */
  362.     
  363.     gResult = ReadFromWritePort(&selectionRead, selection->port);
  364.     if (gResult != noErr) goto CleanUp;
  365.     
  366.     /* Figure out which composite data to use. */
  367.     
  368.     if (DoTarget)
  369.     {
  370.         composite = doc->targetCompositeChannels;
  371.         transparency = doc->targetTransparency;
  372.     
  373.         if (composite == NULL)
  374.         {
  375.             composite = doc->mergedCompositeChannels;
  376.             transparency = doc->mergedTransparency;
  377.         }
  378.     }
  379.     else
  380.     {
  381.         composite = doc->mergedCompositeChannels;
  382.         transparency = doc->mergedTransparency;
  383.     }
  384.             
  385.     /* Allocate the buffers. */
  386.     
  387.     if (!WarnBufferProcsAvailable ())
  388.         {
  389.         gResult = +1;
  390.         goto CleanUp;
  391.         }
  392.         
  393.     #define kBufferSize kBlockRows * (long) kBlockCols
  394.     
  395.     gResult = AllocateBuffer (kBufferSize, &sBuffer);
  396.     if (gResult != noErr) goto CleanUp;
  397.     
  398.     gResult = AllocateBuffer (kBufferSize, &dBuffer);
  399.     if (gResult != noErr) goto CleanUp;
  400.     
  401.     gResult = AllocateBuffer (kBufferSize, &rBuffer);
  402.     if (gResult != noErr) goto CleanUp;
  403.     
  404.     if (transparency != NULL)
  405.         {
  406.         gResult = AllocateBuffer (kBufferSize, &mBuffer);
  407.         if (gResult != noErr) goto CleanUp;
  408.         }
  409.         
  410.     /* Lock the buffers down. */
  411.     
  412.     sData = LockBuffer (sBuffer, false);
  413.     dData = LockBuffer (dBuffer, false);
  414.     rData = LockBuffer (rBuffer, false);
  415.     if (mBuffer != 0) mData = LockBuffer (mBuffer, false);
  416.     
  417.     /* Set up the pixel memory descriptors. */
  418.     
  419.     sDesc.data = sData;
  420.     sDesc.rowBits = kBlockCols * 8;
  421.     sDesc.colBits = 8;
  422.     sDesc.bitOffset = 0;
  423.     sDesc.depth = 8;
  424.     
  425.     dDesc = sDesc;
  426.     dDesc.data = dData;
  427.     
  428.     rDesc = sDesc;
  429.     rDesc.data = rData;
  430.     
  431.     mDesc = sDesc;
  432.     mDesc.data = mData;
  433.     
  434.     rData[0] = kInitRandom; // flag for uninitialized random buffer
  435.     
  436.     /* Count the channels to process. */
  437.     
  438.     if (doc->selection != NULL)
  439.         total += AccountChannel (doc->selection, NULL, selection);
  440.     
  441.     curChannel = composite;
  442.     while (curChannel != NULL)
  443.     {
  444.         if (DoTarget ? curChannel->target : curChannel->shown)
  445.             total += AccountChannel (curChannel, transparency, selection);
  446.                                       
  447.         curChannel = curChannel->next;
  448.     }
  449.         
  450.  
  451.     if (doc->targetLayerMask != NULL && 
  452.        (DoTarget ? doc->targetLayerMask->target : doc->targetLayerMask->shown))
  453.             total += AccountChannel (doc->targetLayerMask, NULL, selection);
  454.             
  455.     curChannel = doc->alphaChannels;
  456.     while (curChannel != NULL)
  457.     {
  458.         if (DoTarget ? curChannel->target : curChannel->shown)
  459.             total += AccountChannel (curChannel, NULL, selection);
  460.                               
  461.         curChannel = curChannel->next;
  462.     }
  463.  
  464.     
  465.     /* Apply any existing selection. */
  466.     
  467.     if (doc->selection != NULL)
  468.         {
  469.         ApplyChannel (globals, doc->selection, &sDesc,
  470.                           NULL, &mDesc,
  471.                           selection, selectionRead, &dDesc,
  472.                           &rDesc, &done, total);
  473.         if (gResult != noErr) goto CleanUp;
  474.         }
  475.     
  476.     /* Apply each of the channels. This isn't the most efficient
  477.     approach since it reads the data back out of the selection
  478.     repeatedly, but it provides a good work out for the code. */
  479.     
  480.     curChannel = composite;
  481.     while (curChannel != NULL)
  482.     {
  483.         if (DoTarget ? curChannel->target : curChannel->shown)
  484.         {
  485.             ApplyChannel (globals, curChannel, &sDesc,
  486.                               transparency, &mDesc,
  487.                               selection, selectionRead, &dDesc,
  488.                               &rDesc, &done, total);
  489.             if (gResult != noErr) goto CleanUp;
  490.         }
  491.                               
  492.         curChannel = curChannel->next;
  493.     }
  494.         
  495.     /* Apply the layer mask. */
  496.     if (doc->targetLayerMask != NULL &&
  497.        (DoTarget ? doc->targetLayerMask->target : doc->targetLayerMask->shown))
  498.     {
  499.         ApplyChannel (globals, doc->targetLayerMask, &sDesc,
  500.                           NULL, &mDesc,
  501.                           selection, selectionRead, &dDesc,
  502.                           &rDesc, &done, total);
  503.         if (gResult != noErr) goto CleanUp;
  504.     }
  505.         
  506.     /* Process the alpha channels. */
  507.     curChannel = doc->alphaChannels;
  508.     while (curChannel != NULL)
  509.     {
  510.         if (DoTarget ? curChannel->target : curChannel->shown)
  511.         {
  512.             ApplyChannel (globals, curChannel, &sDesc,
  513.                               NULL, &mDesc,
  514.                               selection, selectionRead, &dDesc,
  515.                               &rDesc, &done, total);
  516.             if (gResult != noErr) goto CleanUp;
  517.         }
  518.                               
  519.         curChannel = curChannel->next;
  520.     }
  521.     
  522.     CleanUp:
  523.     
  524.     if (sData != NULL) UnlockBuffer (sBuffer);
  525.     if (dData != NULL) UnlockBuffer (dBuffer);
  526.     if (mData != NULL) UnlockBuffer (mBuffer);
  527.     if (rData != NULL) UnlockBuffer (rBuffer);
  528.     
  529.     if (sBuffer != 0) FreeBuffer (sBuffer);
  530.     if (dBuffer != 0) FreeBuffer (dBuffer);
  531.     if (mBuffer != 0) FreeBuffer (mBuffer);    
  532.     if (rBuffer != 0) FreeBuffer (rBuffer);
  533.     
  534.     WriteScriptParams(globals);
  535.  
  536. }